package com.zztl.infiniteBand.util.rsa

import android.util.Base64
import java.io.ByteArrayOutputStream
import java.security.KeyFactory
import java.security.spec.X509EncodedKeySpec
import javax.crypto.Cipher

object RSAUtils {
    private val PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLytoD9eJSLv8fNF/oVXXBqYSADPW2laeYk8KL0eYixaRF5pikPXMrPo48zQqiKV5uREV7f1zafNvJcR9VFIfmTuRf+seSmNixMPWr4gDKVTP3aNwON+5PL1F6J8Ga+ZFfECeg22ZHqNWzPwnxBwm/ReCSG+pze+3PpVBsYwaDtwIDAQAB"

    /**
     * RSA最大加密明文大小
     */
    private val MAX_ENCRYPT_BLOCK = 117

    /**
     * RSA最大解密密文大小
     */
    private val MAX_DECRYPT_BLOCK = 128

    /**
     * 加密算法RSA
     */

    private val KEY_ALGORITHM = "RSA"


    /**
     * 公钥加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    fun encryptByPublicKey(data: String): String {
        val dataByte = data.toByteArray()
//                byte[] keyBytes = Base64.decode(PUBLIC_KEY.getBytes(), Base64.DEFAULT);
        val keyBytes = Base64.decode(PUBLIC_KEY.toByteArray(), Base64.DEFAULT)
        val x509KeySpec = X509EncodedKeySpec(keyBytes)
        val keyFactory = KeyFactory.getInstance(KEY_ALGORITHM)
        val publicK = keyFactory.generatePublic(x509KeySpec)
        // 对数据加密
        // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        val cipher = Cipher.getInstance("RSA/None/PKCS1Padding")
        cipher.init(Cipher.ENCRYPT_MODE, publicK)
        val inputLen = dataByte.size
        val out = ByteArrayOutputStream()
        var offSet = 0
        var cache: ByteArray
        var i = 0
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK)
            } else {
                cache = cipher.doFinal(dataByte, offSet, inputLen - offSet)
            }
            out.write(cache, 0, cache.size)
            i++
            offSet = i * MAX_ENCRYPT_BLOCK
        }
        val encryptedData = out.toByteArray()
        out.close()
        return Base64.encodeToString(encryptedData, Base64.NO_WRAP)
    }

}